昨天的 D05: Qt 排版系統裡,我們已經可以在視窗上添加按鈕了,今天我們就來說明怎麼讓按鈕觸發動作。
大多數的圖形介面程式都是「事件驅動」的。
什麼叫「事件驅動」呢?
「按下按鈕」「敲擊鍵盤」「滑鼠點擊」這些就是事件。程式收到事件後,做出回應。如果沒有事件發生,那程式就靜靜的等待。
所以撰寫 GUI 程式時,很重要的一部分就是連結「事件」和「回應的行動」。
今天要介紹的 signal/slot 信號槽,就是 Qt 處理這事件和回應的機制。
今天的範例一樣是由一個 Qt 專案檔 (.pro
) + 一個 CPP 組成。不知道怎麼設定跟編譯 Qt 程式的人,請參考 D04: 第一支 Qt 程式 。
這是 Qt 專案檔,檔名 myqt-d05.pro
:
QT += core gui widgets # 引入 Qt widgets 模組
TEMPLATE = app # 這是一支應用程式
TARGET = MyApp # 執行檔名稱
SOURCES = d06.cpp # 這支專案有一個 CPP
這是 CPP 檔,檔名 d06.cpp
// 這是 qt-d06.cpp
#include <QApplication>
#include <QWidget>
#include <QHBoxLayout>
#include <QPushButton>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QWidget w;
QHBoxLayout* layout = new QHBoxLayout;
w.setLayout(layout);
QPushButton* button = new QPushButton("關於 Qt");
layout->addWidget(button);
//建立連結
QObject::connect(button, &QPushButton::clicked,
&app, &QApplication::aboutQt);
w.show();
return app.exec();
}
如果你很快的掃過程式碼,你會知道這隻CPP跟昨天的CPP大同小異,唯一差別是今天視窗上只有一個按鈕。而且呼叫了一個沒看過的 QObject::connect()
函數。
Qt 處理事件的奧秘就在 QObject::connect()
函數裡。
QObject::connect(監聽的物件, 監聽的事件, 事件接收者, 事件的處理函數);
前面我們提過撰寫 GUI 程式時連結事件和回應行動是關鍵。QObject::connect()
的功能就是建立這個連結。QObject::connect()
的前兩個參數指定你要監聽的對象和事件,後兩個參數則是指定事件的接收者和怎麼處理。
以我們的程式碼為例子:
QObject::connect(button, &QPushButton::clicked, &app, &QApplication::aboutQt);
這行程式碼的意思是,我們想要監聽 button
按鈕物件的 clicked
(點擊)事件。一旦點擊事件發生了,就呼叫 app
物件的 QApplication::aboutQt()
函數。
QApplication::aboutQt() 是 QApplication 的成員函數,功用是彈出當前 Qt 的版本和版權等等資訊。
一旦執行過這行程式 QObject::connect()
,事件和處理函數就連接起來了!
接著請你編譯並執行程式碼,點擊按鈕看看,確認是不是彈出視窗了?
在 Qt 裡面,我們把這些事件統稱作「signal(信號)」。QPushButton 物件最常用的信號就是 clicked (點擊),你可查閱官方文件看有哪些其他信號。
而事件的回應行動,就叫做「slot(槽)」。slot 通常是一個物件的成員函數。一旦建立連接,該物件就成了專門負責處理這事件的負責人。
請注意,連結 signal/slot 的時候,傳入的是成員函數的指標,函數名前面要加上一個 &
符號。(例如 &QPushButton::clicked
和&QApplication::aboutQt
)
Qt 已經有內建好許多的 signal & slot 可供我們使用,後續的文章中會陸續介紹。當然,還可以定義自己的 signal & slot 這個也會在後面介紹。